﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using Autofac;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using yiCommerce.Core;
using yiCommerce.Models.Comments;
using yiCommerce.Service.Statuses;

namespace yiCommerce.Hubs
{
     [HubName("comments")]
    public class CommentsHub:Hub
    {
         private static readonly ConcurrentDictionary<string, CustomerConnection> customerConnections = new ConcurrentDictionary<string, CustomerConnection>(StringComparer.InvariantCultureIgnoreCase);
         private ICommentService _commentService;
         private IWorkContext _workContext;
         readonly ILifetimeScope _hubLifetimeScope;
      

         public CommentsHub()
         {
             _workContext = DependencyResolver.Current.GetService<IWorkContext>();
             _commentService= DependencyResolver.Current.GetService<ICommentService>();
          
         }
          
        
         public void SendComment(SendCommentMessage message)
         {

             var commentId = _commentService.AddComment(int.Parse(message.StatusId), _workContext.CurrentCustomer.Id, message.Text);
             var comment = _commentService.GetComment(commentId);
             var commentModel = yiCommerce.Mapper.StatusMapper.ToCommentModel(comment);
             ClientReceive(commentModel);
         }

         protected override void Dispose(bool disposing)
         {
             // Dipose the hub lifetime scope when the hub is disposed.
             if (disposing && _hubLifetimeScope != null)
                 _hubLifetimeScope.Dispose();

             base.Dispose(disposing);
         }

         public override Task OnConnected()
         {

             System.Collections.Specialized.NameValueCollection queryString = Context.Request.QueryString;
             string statusId= queryString["StatusId"];

             string connectionId = Context.ConnectionId;

             var newConnection = customerConnections.GetOrAdd(statusId, _ => new CustomerConnection()
             {
                 Name = statusId,
                 ConnectionIds = new List<string>()
             });

             newConnection.ConnectionIds.Add(connectionId);

             return base.OnConnected();
          
         }


         private void ClientReceive(CommentModel commentModel)
         {

             var conn = this.GetConnection(commentModel.StatusId.ToString());
             foreach (var connId in conn.ConnectionIds)
             {
                  Clients.Client(connId).messageReceived(commentModel);
             }

              Clients.Caller.success("success");
             
         }

        
         private CustomerConnection GetConnection(string statusId)
         {

             CustomerConnection connection;
             customerConnections.TryGetValue(statusId, out connection);

             return connection;
         }

         public override Task OnDisconnected()
         {

             var query = from c in customerConnections
                         where c.Value.ConnectionIds.Contains(Context.ConnectionId)
                         select c;
             var conns = query.ToList();
             if (conns != null)
             {
                 foreach (var c in conns)
                 {
                     c.Value.ConnectionIds.Remove(Context.ConnectionId);
                 }
             }

            

             return base.OnDisconnected();
         }
    }

    public class SendCommentMessage
    {
        public string StatusId { get; set; }
        public string Text { get; set; }
    }
}